home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / pc / ABUSESRC.ZIP / AbuseSrc / imlib / port / dos4gw / timing.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-02-16  |  6.2 KB  |  264 lines

  1. #include <time.h>
  2. #include "timing.hpp"
  3. #include <dos.h>
  4. #include <stdlib.h>
  5. #include <i86.h>
  6. #include <stdio.h>
  7. #include <conio.h>
  8. #include "dprint.hpp"
  9. #include <string.h>
  10.  
  11.  
  12. static void (__interrupt __far *prev_int8)()=NULL;
  13. volatile unsigned long tick_counter,start_tick_counter; // note : if timer handler is installed for more than 497 days then
  14.                                                         // tick_counter will overflow.  ** don't use this in OS code **
  15.  
  16. void (*install_timer_handler)(void (*fun)())=NULL;   // function to install timer
  17. void (*uninstall_timer_handler)()=NULL;
  18. unsigned char timer_installed=0;
  19.  
  20.  
  21. static dostime_t dos_start_time;
  22. static dosdate_t dos_start_date;
  23. static chain_on=0,chain_counter=0;
  24. int total_timer_calls=0;
  25.  
  26. #define MAX_TIMER_CALLS 10
  27.  
  28. #define TICKS_PER_SEC 100
  29.  
  30. struct
  31. {
  32.   int and_call_mask;
  33.   void ( *fun)();  
  34. } timer_calls[MAX_TIMER_CALLS];
  35.  
  36. void add_timer_call(void ( *fun)(), int and_call_mask)
  37. {
  38.   if (total_timer_calls>=MAX_TIMER_CALLS)
  39.   {
  40.     dprintf("Too many timer calls installed\n");
  41.     exit(0);
  42.   }
  43.   timer_calls[total_timer_calls].fun=fun;
  44.   timer_calls[total_timer_calls].and_call_mask=and_call_mask;
  45.   total_timer_calls++;  
  46. }
  47.  
  48. void remove_timer_call(void ( *fun)())
  49. {
  50.   for (int i=0;i<total_timer_calls;i++)
  51.   {
  52.     if (timer_calls[i].fun==fun)
  53.     {
  54.       for (int j=i;j<total_timer_calls-1;j++)        
  55.         timer_calls[j]=timer_calls[j+1];
  56.       total_timer_calls--;
  57.       return ;
  58.     }
  59.   }
  60.   dprintf("remove_timer_call : call not installed\n");
  61.   exit(0);
  62. }
  63.  
  64. void cli();
  65. #pragma aux cli = "cli";
  66.  
  67. void sti();
  68. #pragma aux sti = "sti";
  69.  
  70.  
  71.  
  72. static int inside=0;  // check for re-entry
  73. void __interrupt __far new_timer_int () 
  74.   outp(0x20,0x20);          // signal int chip that ints can continue
  75.   tick_counter++;
  76.  
  77.   if (!inside)
  78.   {    
  79.     inside=1;    
  80.     sti();                  // turn interrupts back on
  81.  
  82.  
  83.     for (int i=0;i<total_timer_calls;i++)
  84.       if ((tick_counter&timer_calls[i].and_call_mask)==0)
  85.         timer_calls[i].fun();
  86.     inside=0;
  87.   } else sti();                  // turn interrupts back on
  88.  
  89.   chain_counter++;               // see if we need to call the normal DOS intr yet
  90.   if (chain_counter==chain_on)
  91.   {
  92.     chain_counter=0;
  93.     _chain_intr(prev_int8);
  94.   }
  95.  
  96.  
  97. void timer_stub()  // this should be called int timer_init has been called and install_timer_handler!=NULL
  98. {
  99.   tick_counter++;
  100.  
  101.   if (!inside)
  102.   {
  103.     inside=1;
  104.     for (int i=0;i<total_timer_calls;i++)
  105.       if ((tick_counter&timer_calls[i].and_call_mask)==0)
  106.         timer_calls[i].fun();
  107.     inside=0;
  108.   }
  109. }
  110.  
  111. void timer_init()
  112. {
  113.   if (install_timer_handler)
  114.   {
  115.     install_timer_handler(timer_stub);
  116.     timer_installed=1;
  117.   } else
  118.   {
  119.     if (prev_int8)  
  120.       fprintf(stderr,"timer_init called twice (not good)\n");
  121.     else
  122.     {
  123.       _dos_gettime(&dos_start_time);             // get initail time
  124.       _dos_getdate(&dos_start_date);             // get initail date
  125.  
  126.       prev_int8=_dos_getvect(8);  
  127.       _dos_setvect(0x8008,new_timer_int);       // set protected mode int 8
  128.  
  129.       int new_divsor;
  130.       if (TICKS_PER_SEC<18.2)
  131.       {
  132.         new_divsor=0xffff;
  133.     chain_on=1;
  134.       }
  135.       else
  136.       {
  137.     chain_on=TICKS_PER_SEC/18.2;
  138.         new_divsor=0xffff/chain_on;
  139.       }
  140.  
  141.       chain_counter=0;
  142.       cli();
  143.       outp(0x43,0x36);                      // set timer speed
  144.       outp(0x40,(new_divsor&0xff)); 
  145.       outp(0x40,((new_divsor&0xff00)>>8));
  146.       sti();
  147.  
  148.       timer_installed=1;
  149.     }
  150.     atexit(timer_uninit);
  151.     start_tick_counter=tick_counter=clock();
  152.   }
  153. }
  154.  
  155. static char dim[12]={31,  // Jan
  156.              29,  // Feb
  157.              31,  // March
  158.              30,  // Apr
  159.              31,  // May
  160.              30,  // June
  161.              31,  // July
  162.              30,  // Aug
  163.              31,  // Sept
  164.              31,  // October
  165.              30,  // Nov
  166.              31}; // Dec
  167.  
  168. static int days_in_month(long month, long year)
  169. {
  170.   if (month==1 && (((year-1)%4)==0))   // check for leap-year
  171.     return 28;
  172.   else return dim[month];
  173. }
  174.  
  175. void timer_uninit()
  176. {
  177.   chain_on=0;
  178.   if (timer_installed)
  179.   {
  180.     if (uninstall_timer_handler)
  181.       uninstall_timer_handler();
  182.     else
  183.     {
  184.       if (prev_int8)
  185.       {
  186.     outp(0x43,0x36);                      // set timer speed back to 18.2
  187.     outp(0x40,0); 
  188.     outp(0x40,0); 
  189.     _dos_setvect(8,prev_int8);
  190.  
  191.  
  192.        // don't try to restore the clock, we used chain_intr
  193. /*    unsigned long ticks_passed=tick_counter-start_tick_counter;
  194.     unsigned long hsec=ticks_passed*100/TICKS_PER_SEC;
  195.  
  196.     // now calculate how much time we stole from DOS and adjust the clock
  197.     dos_start_time.hsecond=((long)dos_start_time.hsecond+hsec)%100;
  198.     dos_start_time.second=((long)dos_start_time.second+hsec/100)%60;
  199.     dos_start_time.minute=((long)dos_start_time.minute+hsec/(100*60))%60;
  200.     dos_start_time.hour=((long)dos_start_time.hour+hsec/(100*60*60))%24;
  201.     
  202.     long days=hsec/(100*60*60*24);
  203.     while (days)
  204.     {
  205.       dos_start_date.dayofweek=(dos_start_date.dayofweek+2)%7-1;
  206.       dos_start_date.day=dos_start_date.day+1;
  207.       if (days_in_month(dos_start_date.month,dos_start_date.year)>dos_start_date.day)
  208.       {
  209.         dos_start_date.day=1;
  210.         dos_start_date.month++;
  211.         if (dos_start_date.month>12)
  212.         {
  213.           dos_start_date.month=1;
  214.           dos_start_date.year++;
  215.         }
  216.       }
  217.       days--;
  218.     } */
  219.  
  220.     _dos_settime(&dos_start_time);
  221.     _dos_setdate(&dos_start_date);
  222.  
  223.     prev_int8=NULL;    
  224.       }
  225.     }
  226.     timer_installed=0;
  227.   }
  228. }
  229.  
  230. void time_marker::get_time()
  231. {
  232.   seconds=0;
  233.   if (timer_installed)
  234.     micro_seconds=tick_counter*1000/TICKS_PER_SEC;
  235.   else
  236.     micro_seconds=clock()*10;
  237. }
  238.  
  239. time_marker::time_marker()
  240. {
  241.   seconds=0;
  242.   if (timer_installed)
  243.     micro_seconds=tick_counter*1000/TICKS_PER_SEC;  
  244.   else
  245.     micro_seconds=clock()*10;
  246. }
  247.  
  248. double time_marker::diff_time(time_marker *other)
  249. {
  250.   return (double)(micro_seconds-other->micro_seconds)/1000.0;  
  251. }
  252.  
  253. void milli_wait(unsigned wait_time)
  254. {
  255.   if (timer_installed)
  256.   {
  257.     unsigned long wait_tick=wait_time*10/TICKS_PER_SEC+tick_counter;
  258.     while (tick_counter<wait_tick) ;
  259.   } else delay(wait_time);                    // timer not installed
  260. }
  261.  
  262.